#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework import serializers
from goods.models import SKU

import time


class CartSKUSerializer(serializers.ModelSerializer):
    """
    购物车商品数据序列化器
    """
    """
      购物车商品数据序列化器
      """
    count = serializers.IntegerField(label='数量')

    class Meta:
        model = SKU
        fields = ('id', 'name', 'default_image_url', 'price', 'count')


class PlaceOrderSerializer(serializers.Serializer):
    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


from django.db import transaction
from django_redis import get_redis_connection
from decimal import Decimal
from .models import OrderInfo, OrderGoods


class CreateOrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    def create(self, validated_data):
        """
            1.根据时间的年月十分秒微秒以及用户id（９位）生成一个订单id
            2.获取user,address,pay_method数据
            3.初始化运费,购买个数和价格信息
            4.生成状态信息
            5.生成订单
            6.从redis中获取商品的数据（bytes）
            7.获取选中的数据cart {sku_id:count,sku_id:count}
            8.对数据进行遍历

            保存商品的信息的前提是有订单
        """
        # １．获取用户信息
        user = self.context['request'].user
        # ２．生成一个订单id
        from django.utils import timezone
        order_id = timezone.now().strftime('%Y%m%d%H%M%S%f') + '%09d' % user.id
        # ３．获取user,address,pay_method数据
        address = validated_data.get('address')
        pay_method = validated_data.get('pay_method')

        total_count = 0

        total_amount = Decimal('0')
        # 运费
        freight = Decimal('10.0')

        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        # 创建事物，就是有多个增删改查的操作
        with transaction.atomic():
            try:
                # 创建事物的保存点，如果回滚的时候就回滚到这里
                save_id = transaction.savepoint()
                # 生成订单
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=total_count,
                    total_amount=total_amount,
                    freight=freight,
                    pay_method=pay_method,
                    status=status

                )

                # 从redis获取商品的数据(bytes)
                redis_conn = get_redis_connection('cart')
                redis_cart = redis_conn.hgetall('cart_%s' % user.id)
                redis_selected_ids = redis_conn.smembers('cart_selected_%s' % user.id)

                cart = {}
                # 获取选中的数据
                for sku_id in redis_selected_ids:
                    cart[int(sku_id)] = int(redis_cart[sku_id])

                # 对数据进行遍历
                for sku_id, count in cart.items():
                    sku = SKU.objects.get(pk=sku_id)

                    # 判断商品的库存是否充足
                    if sku.stock < count:
                        # 抛异常的时候就应该回滚
                        transaction.savepoint_rollback(save_id)
                        raise serializers.ValidationError('库存不足')
                    #
                    # sku.stock -= count  # 库存减少count
                    # sku.sales += count  # 商品销量加count
                    # sku.save()
                    time.sleep(8)

                    # 处理并发问题,先查处之前的库存
                    old_stock = sku.stock

                    new_stock = sku.stock - count
                    new_sales = sku.sales + count
                    # 更新数据的时候先查询
                    rect = SKU.objects.filter(pk=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)

                    if rect == 0:
                        raise serializers.ValidationError('下单失败')

                    # 对订单的个数和价格进行累加
                    order.total_count += count
                    order.total_amount += (sku.price*count)
                    # 订单信息入库

                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=count,
                        price=sku.price
                    )
            except Exception:

                transaction.savepoint_rollback(save_id)

                raise serializers.ValidationError('下单失败')
            else:
                order.save()
                # 代码执行成功则保存提交事物
                transaction.savepoint_commit(save_id)

        return order
